package rest.jbpm.wrappers;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.PathParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jersey.api.uri.UriTemplate;
import javax.ws.rs.WebApplicationException;

public class ResourceWrapper {
	
	private static Logger log = LoggerFactory.getLogger(ResourceWrapper.class);
	private UriTemplate uriTemplate;
	private Method method;
	private Object resource;
	
	public ResourceWrapper(UriTemplate uriTemplate, Object resource, Method method) {
		
		this.uriTemplate = uriTemplate;
		this.resource = resource;
		this.method = method;
		
	}
	
	public Object getResource() {
		return resource;
	}
	
	public Method getMethod() {
		return method;
	}
	
	public UriTemplate getUriTemplate() {
		return uriTemplate;
	}
	
	public boolean isUriMatch(String uri) {
		
		Map<String,String> map = new HashMap<String,String>();
		return uriTemplate.match(uri,map);
		
	}
	
	public Object invoke(String uri) {
        
        Map<String,String> map = new HashMap<String,String>();
            
        if(uriTemplate.match(uri,map)){

            Annotation[][] parAnn=method.getParameterAnnotations();                
            Object[] argArray=new Object[parAnn.length];
            int i=0;
            for(Annotation[] annArr: parAnn)
             argArray[i++]=map.get(((PathParam)annArr[0]).value());

            try {
                return method.invoke(resource, argArray);
            } catch (Exception e) {
                if(e instanceof InvocationTargetException) {
                    log.info("{}.{}({}) call caused an exception {} {}",
                            new Object [] {resource.getClass().getName(),method.getName(),
                            argArray, e.getCause(), e.getMessage()});
                } else {
                    log.error("failed to invoke {}.{}({}) due to {}",
                        new Object [] {resource.getClass().getName(),method.getName(),
                            argArray,e});
                }           
            }
        }
		
		return null; 
	}

}
